/*
Mapsend Exchange Format (.mxf)
(Maptech Terrain Navigator, Terrain Professional, Take a Hike)
- (Aka Yet Another CSV Format)
+ (AKA Yet Another CSV Format)
- Contributed to gpsbabel by Alex Mottram
+ Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com)
- LAT,LON,"WPT Name", "Big Name","Small Name",COLORxFF,(int)ICON
+ LAT, LON, "Waypoint Name", "Big Name", "Small Name", COLOR, ICON
- as described at: www.memory-map.co.uk/downloads/PDF/mm_tsb3_import_export_text_files.pdf
- tested against ExpertGPS import/export .mxf files.
+ As described in Maptech Terrain Navigator Help File.
+ Tested against Terrain Navigator and ExpertGPS import/export .MXF files.
Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
static FILE *file_in;
static FILE *file_out;
-/* remember what dave & gamera say about pointer math... */
static char *
-cvsstringclean(char * string)
+csvstringclean(char * string)
{
static char * p1 = NULL;
char * p2 = NULL;
return (p1);
}
-/* string parser. sorta like strtok with quotes & pointers.. */
+/* string parser. sorta like strtok with quotes & pointers.. */
+/* designed to handle quoted and delimited data within quotes. */
static char *
csvparse(char *stringstart, char *delimiter)
{
static char *tmp = NULL;
size_t dlen;
int quotedepth = 0;
+ short int dfound;
if (!p) {
p = stringstart;
sp = p;
dlen = strlen(delimiter);
+ dfound = 0;
- while ((*p) && (! tmp)) {
+ while ((*p) && (! dfound)) {
if (*p == '"') {
if (quotedepth)
quotedepth--;
}
if ((!quotedepth) && (strncmp(p, delimiter, dlen) == 0)) {
- tmp = (char *) calloc((p - sp) + 1, sizeof(char));
- if (! tmp) {
- fatal(MYNAME ": cannot allocate memory\n");
- }
- strncpy(tmp, sp, (p - sp));
+ dfound = 1;
+
+ } else {
+ p++;
}
- p++;
- }
-
- if (!tmp) {
- tmp = (char *) calloc((p - sp) + 1, sizeof(char));
- if (! tmp) {
- fatal(MYNAME ": cannot allocate memory\n");
- }
+ }
- strncpy(tmp, sp, (p - sp));
+ tmp = (char *) calloc((p - sp) + 1, sizeof(char));
- p = NULL;
+ if (! tmp) {
+ fatal(MYNAME ": cannot allocate memory\n");
}
- if (tmp) {
- return (tmp);
+ strncpy(tmp, sp, (p - sp));
+
+ if (dfound) {
+ /* skip over the delimiter */
+ p += dlen;
+ } else {
+ /* end of the line */
+ p = NULL;
}
- return (NULL);
+ return (tmp);
}
static void
}
s = buff;
- s = csvparse(s, ",");
+ s = csvparse(s, ", ");
i = 0;
while (s) {
wpt_tmp->position.longitude.degrees = atof(s);
break;
case 2:
- wpt_tmp->description = strdup(cvsstringclean(s));
+ wpt_tmp->description = strdup(csvstringclean(s));
break;
case 3:
- wpt_tmp->shortname = strdup(cvsstringclean(s));
+ wpt_tmp->shortname = strdup(csvstringclean(s));
break;
case 4:
/* ignore. another name-type */
break;
default:
/* whoa! nelly */
- printf ("%s: Warning: data fields on line %d exceed specification.\n",
+ fprintf (stderr, "%s: Warning: data fields on line %d exceed specification.\n",
MYNAME, linecount);
break;
}
i++;
- s = csvparse(NULL, ",");
+ s = csvparse(NULL, ", ");
}
if (i != 7) {
free(wpt_tmp);
- printf ("%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n",
+ fprintf (stderr, "%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n",
MYNAME, i, linecount);
} else {
waypt_add(wpt_tmp);
}
} else {
- /* this complains too much
- * printf ("%s: WARNING - blank line at line %d.\n", MYNAME, linecount);
- */
+ /* empty line */
}
} while (!feof(file_in));
static void
mxf_disp(waypoint * wpt)
{
- double lon, lat;
int icon = 47; /* default to "dot" */
const char *color_hex = "ff0000";
- lon = wpt->position.longitude.degrees;
- lat = wpt->position.latitude.degrees;
-
fprintf(file_out, "%08.5f, %08.5f, \"%s\", \"%s\", \"%s\", %s, %d\n",
- lat, lon,
+ wpt->position.latitude.degrees, wpt->position.longitude.degrees,
wpt->description, wpt->shortname, wpt->description,
color_hex, icon);
-
}
static void
waypt_disp_all(mxf_disp);
}
-
ff_vecs_t mxf_vecs = {
rd_init,
wr_init,
data_write,
};
-
-/*
- Excerpt from Maptech help file.
-
- Below is an example of the .MXF file format:
-
- 43.7601389, -071.2791299, "Cottonwood", "Cttnwd", "A very large tree", 800080, 137
- 43.7617236, -071.2917695, "Fencepost", "Fncpst", "", 808080, 14
- 43.7576237, -071.2888850, "Aspen", "Aspen", "", ffff, 137
- 43.7562457, -071.2777147, "Cache", "Cache", "", ff, 138
- 43.7576583, -071.2701399, "Tent site", "Tntst", "", ff, 111
-*/
/*
PocketStreets 2002 Pushpin Files
- Contributed to gpsbabel by Alex Mottram.
+ Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com)
Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
*/
#include "defs.h"
-
#include <ctype.h>
#include <math.h> /* for M_PI */
-#define MYNAME "PSP"
+#define MYNAME "PSP"
-/*#define _DEBUG_PSP 1*/
#define MAXPSPSTRINGSIZE 256
#define MAXPSPOUTPUTPINS 8192 /* Any more points than this is ludicrous */
static FILE *psp_file_in;
static FILE *psp_file_out;
-#ifdef _DEBUG_PSP
-static void
-dump_bufferstuff(char * header, char * buffer, int bufferlen)
-{
- int i;
+static int
+psp_fread(void *buff, size_t size, size_t members, FILE * fp) {
+ size_t br;
- printf("%s\n--------\n", header);
+ br = fread(buff, size, members, fp);
+
+ if (br != members) {
+ fatal(MYNAME ": requested to read %d bytes, read %d bytes.\n", members, br);
+ }
- for (i = 0 ; i < bufferlen ; i++) {
- printf("%0.2X ", (unsigned char)buffer[i]);
- }
- printf("\n");
+ return (br);
+}
+
+static int
+valid_psp_header(char * header, int len) {
+ char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x00 }; /* 1niP <stop> */
+ char *p, *s;
+
+ if (len != 32) {
+ return (-1);
+ }
+
+ p = header_bytes;
+ s = header;
+
+ while (*p) {
+ if (*p++ != *s++) {
+ return(-1);
+ }
+ }
+
+ return (0);
}
-#endif
static char *
buffer_washer(char * buff, int buffer_len)
{
int i;
-
+
for (i = 0 ; i < buffer_len - 1; i++) {
if (buff[i] == '\0') {
memcpy(&buff[i], &buff[i+1], buffer_len - i);
static void
psp_rd_init(const char *fname)
{
- psp_file_in = fopen(fname, "r");
+ psp_file_in = fopen(fname, "rb");
if (psp_file_in == NULL) {
fatal(MYNAME ": Cannot open %s for reading\n", fname);
}
static void
psp_wr_init(const char *fname)
{
- psp_file_out = fopen(fname, "w");
+ psp_file_out = fopen(fname, "wb");
if (psp_file_out == NULL) {
fatal(MYNAME ": Cannot open %s for writing\n", fname);
}
static void
psp_read(void)
{
- char buff[MAXPSPSTRINGSIZE + 1];
+ char buff[MAXPSPSTRINGSIZE + 1];
double radians;
waypoint *wpt_tmp;
int stringsize;
short int pincount;
/* 32 bytes - file header */
- fread(&buff[0], 1, 32, psp_file_in);
-
+ psp_fread(&buff[0], 1, 32, psp_file_in);
+
+ if (valid_psp_header(buff, 32) != 0) {
+ fatal(MYNAME ": input file does not appear to be a valid .PSP file.\n");
+ }
+
pincount = *(short int *)&buff[12];
-
+
while (pincount--) {
wpt_tmp = calloc(sizeof(*wpt_tmp),1);
/* things we will probably never know about this waypoint */
/* coming from a pushpin file. */
- /*
+ /*
wpt_tmp->creation_time;
wpt_tmp->position.altitude.altitude_meters;
wpt_tmp->url;
wpt_tmp->url_link_text;
wpt_tmp->icon_descr; TODO: map this.
*/
-
+
/* 4 bytes at start of record */
/* coming out of S&T, this 1st byte is probably the pin # (0x01, 0x02, etc...) */
/* coming from pocketstreets, it's generally 0x00. Sometimes 0xC3. ? */
-
- fread(&buff[0], 1, 4, psp_file_in);
+
+ psp_fread(&buff[0], 1, 4, psp_file_in);
/* 1 byte, unkown */
- fread(&buff[0], 1, 1, psp_file_in);
+ psp_fread(&buff[0], 1, 1, psp_file_in);
/* 8 bytes - latitude in radians */
- fread(&buff[0], 1, 8, psp_file_in);
+ psp_fread(&buff[0], 1, 8, psp_file_in);
radians = *(double *)&buff[0];
wpt_tmp->position.latitude.degrees = (radians * 180.0) / M_PI;
/* 8 bytes - longitude in radians */
- fread(&buff[0], 1, 8, psp_file_in);
+ psp_fread(&buff[0], 1, 8, psp_file_in);
radians = *(double *)&buff[0];
wpt_tmp->position.longitude.degrees = (radians * 180.0) / M_PI;
/* 1 byte - pin display properties */
- fread(&buff[0], 1, 1, psp_file_in);
+ psp_fread(&buff[0], 1, 1, psp_file_in);
/* 3 bytes - unknown */
- fread(&buff[0], 1, 3, psp_file_in);
+ psp_fread(&buff[0], 1, 3, psp_file_in);
- /* 1 bytes - icon 0x00 - 0x27 */
- fread(&buff[0], 1, 1, psp_file_in);
+ /* 1 bytes - icon 0x00 - 0x27 */
+ psp_fread(&buff[0], 1, 1, psp_file_in);
/* 3 bytes - unknown */
- fread(&buff[0], 1, 3, psp_file_in);
+ psp_fread(&buff[0], 1, 3, psp_file_in);
/* 1 byte - string size */
- fread(&buff[0], 1, 1, psp_file_in);
+ psp_fread(&buff[0], 1, 1, psp_file_in);
stringsize = buff[0];
stringsize *= 2;
-
+
if (stringsize > MAXPSPSTRINGSIZE) {
fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE);
}
/* stringsize bytes - string data */
- fread(&buff[0], 1, stringsize, psp_file_in);
+ psp_fread(&buff[0], 1, stringsize, psp_file_in);
buffer_washer(buff, stringsize);
-#ifdef _DEBUG_PSP
- printf ("string1: [%s]\n", buff);
-#endif
-
wpt_tmp->shortname = strdup(buff);
/* 1 bytes string size */
- fread(&buff[0], 1, 1, psp_file_in);
+ psp_fread(&buff[0], 1, 1, psp_file_in);
stringsize = buff[0];
stringsize *= 2;
fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE);
}
-#ifdef _DEBUG_PSP
- printf ("string2: there are %d bytes to follow at offset %ld\n", stringsize, ftell(psp_file_in));
-#endif
-
- /* stringsize bytes - string data */
- fread(&buff[0], 1, stringsize, psp_file_in);
+ /* stringsize bytes - string data */
+ psp_fread(&buff[0], 1, stringsize, psp_file_in);
buffer_washer(buff, stringsize);
-#ifdef _DEBUG_PSP
- printf ("string2: [%s]\n", buff);
-#endif
wpt_tmp->description = strdup(buff);
/* 1 bytes - string size */
- fread(&buff[0], 1, 1, psp_file_in);
+ psp_fread(&buff[0], 1, 1, psp_file_in);
stringsize = buff[0];
stringsize *= 2;
fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE);
}
-
-#ifdef _DEBUG_PSP
- printf ("string: there are %d bytes to follow at offset %ld\n", stringsize, ftell(psp_file_in));
-#endif
-
/* stringsize bytes - string data (address?) */
- fread(&buff[0], 1, stringsize, psp_file_in);
+ psp_fread(&buff[0], 1, stringsize, psp_file_in);
buffer_washer(buff, stringsize);
-#ifdef _DEBUG_PSP
- printf ("string3: [%s]\n", buff);
-#endif
-
- waypt_add(wpt_tmp);
- }
-
-
+ waypt_add(wpt_tmp);
+ }
}
static void
/* 4 leading bytes */
memset(&tbuf, '\0', sizeof(tbuf));
fwrite(&tbuf, 1, 4, psp_file_out);
-
+
/* my test files seem to always have this byte as 0x03, */
/* although nothing seems to really care. */
c = 0x03;
-
+
/* 1 unknown bytes */
fwrite(&c, 1, 1, psp_file_out);
fwrite(&lon, 1, 8, psp_file_out);
/* 1 byte - pin properties */
- c = 0x14; /* display pin on! display notes on! */
+ c = 0x14; /* display pin name on! display notes on! */
fwrite(&c, 1, 1, psp_file_out);
memset(&tbuf, '\0', sizeof(tbuf));
/* 3 unknown bytes */
- fwrite(&tbuf, 1, 3, psp_file_out);
+ fwrite(&tbuf, 1, 3, psp_file_out);
/* 1 icon byte 0x00 = PIN */
fwrite(&tbuf, 1, 1, psp_file_out);
c = strlen(wpt->shortname);
/* 1 string size */
- fwrite(&c, 1, 1, psp_file_out);
+ fwrite(&c, 1, 1, psp_file_out);
for (i = 0 ; wpt->shortname[i] ; i++) {
fwrite(&wpt->shortname[i], 1, 1, psp_file_out); /* char */
/* just for the hell of it, we'll scrap the third string. */
c = strlen(tbuf);
/* 1 byte string size */
- fwrite(&c, 1, 1, psp_file_out);
+ fwrite(&c, 1, 1, psp_file_out);
for (i = 0 ; tbuf[i] ; i++) {
fwrite(&tbuf[i], 1, 1, psp_file_out); /* char */
fwrite(&tbuf[0], 1, 1, psp_file_out); /* null */
}
-
}
static void
/* offset 0x0C - 0x0D = 2 byte pin count */
s = waypt_count();
-
+
if (s > MAXPSPOUTPUTPINS) {
- fatal(MYNAME ": output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS);
+ fatal(MYNAME ": attempt to output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS);
}
/* insert waypoint count into header */
memcpy(&header_bytes[12], &s, 2);
fwrite(&header_bytes, 1, 32, psp_file_out);
-
+
waypt_disp_all(psp_disp);
}